package code.oldCode.feishuSpecializedTraining.binary_tree;

import utils.TreeNode;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class MyBinaryTree2 {
    // 226. 翻转二叉树
    public TreeNode invertTree(TreeNode root) {
        // 递归法
        invertTree_DIGUI(root);
        return root;
    }

    public void invertTree_DIGUI(TreeNode root) {
        if (root == null)
            return;
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        invertTree_DIGUI(root.left);
        invertTree_DIGUI(root.right);
    }

    public TreeNode invertTree_(TreeNode root) {
        // 非递归：辅助栈
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node == null)
                continue;
            stack.push(node.left);
            stack.push(node.right);
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;
        }

        return root;
    }

    // 101. 对称二叉树
    public boolean isSymmetric(TreeNode root) {
        // 递归
        if (root == null)
            return true;
        return isGood(root.left, root.right);
    }

    public boolean isGood(TreeNode node1, TreeNode node2) {
        if (node1 == null && node2 == null)
            return true;
        if (node1 == null || node2 == null)
            return false;
        if (node1.val != node2.val)
            return false;
        boolean ans1 = isGood(node1.left, node2.right);
        boolean ans2 = isGood(node1.right, node2.left);
        return ans1 && ans2;
    }

    public boolean isSymmetric_(TreeNode root) {
        // 非递归
        if (root == null)
            return true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root.left);
        queue.offer(root.right);
        while (!queue.isEmpty()) {
            TreeNode node1 = queue.poll();
            TreeNode node2 = queue.poll();
            if (node1 == null && node2 == null)
                continue;
            if (node1 == null || node2 == null)
                return false;
            if (node1.val != node2.val)
                return false;
            queue.offer(node1.left);
            queue.offer(node2.right);
            queue.offer(node1.right);
            queue.offer(node2.left);
        }
        return true;
    }

    // 104. 二叉树的最大深度
    public int maxDepth(TreeNode root) {
        // 递归
        return getMaxDepth(root, 0);
    }

    public int getMaxDepth(TreeNode root, int depth) {
        if (root == null)
            return depth;
        int leftDepth = getMaxDepth(root.left, depth + 1);
        int rightDepth = getMaxDepth(root.right, depth + 1);
        return Math.max(leftDepth, rightDepth);
    }

    public int maxDepth_(TreeNode root) {
        // 层次遍历
        int depth = 0;
        if (root == null)
            return depth;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            depth++;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                if (node.left != null)
                    queue.offer(node.left);
                if (node.right != null)
                    queue.offer(node.right);
            }
        }

        return depth;
    }

    // 111. 二叉树的最小深度
    public int minDepth(TreeNode root) {
        // 非递归
        if (root == null)
            return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            depth++;
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                // 是叶子结点？
                if (node.left == null && node.right == null)
                    return depth;
                if (node.left != null)
                    queue.offer(node.left);
                if (node.right != null)
                    queue.offer(node.right);
            }
        }
        return depth;
    }
}
